#include "PhysicManager.h"
#include "Core.h"
#include "Manager.h"
#include <algorithm>

PhysicManager PhysicManager::mInstance;

PhysicManager::PhysicManager()
{
	mWorldAABB.lowerBound.Set(-800.0f, -800.0f);
	mWorldAABB.upperBound.Set(800.0f, 800.0f);

	//gravity
    //mGravity = 10.0f
    b2Vec2 gravity(0.0f, 10.0f);
	// Do we want to let bodies sleep?
	bool doSleep = true;

	// Construct a world object, which will hold and simulate the rigid bodies.
	mWorld = new b2World(mWorldAABB, gravity, doSleep);

	mTimeStep = 1.0f / 60.0f;
	mIterations = 10;
	Core::GetInstance().AddFrameListener(this);

	//Core::GetInstance().AddFrameListener(this);
}
void PhysicManager::SetLowerBounds(float x, float y)
{
    mWorldAABB.lowerBound.Set(x, y);
}
void PhysicManager::SetUpperBounds(float x, float y)
{
    mWorldAABB.upperBound.Set(x, y);
}
bool PhysicManager::FrameStarted(float timeSinceLastFrame)
{
    mWorld->Step(mTimeStep, mIterations);
    ObjectListIterator = ObjectList.begin();
    for(;ObjectListIterator!=ObjectList.end();++ObjectListIterator)
    {
        (*ObjectListIterator)->Update();
    }
    return true;
}

bool PhysicManager::FrameEnded()
{

}
PhysicObject* PhysicManager::CreateBox(Image* img, int posX, int posY, float density, float friction)
{
    b2Body* body;
    b2BodyDef bodyDef;
    bodyDef.position.Set(posX, posY);
    body = mWorld->CreateBody(&bodyDef);
    // Define box shape for our dynamic body.
    b2PolygonDef shapeDef;
    shapeDef.SetAsBox(img->GetSurface()->w/2, img->GetSurface()->h/2);
    // Set the box density to be non-zero, so it will be dynamic.
    shapeDef.density = 200.0f;
    // Override the default friction.
    shapeDef.friction = 0.5f;
    //shapeDef.restitution = 0.05f;
    // Add the shape to the body.
    body->CreateShape(&shapeDef);
    // Now tell the dynamic body to compute it's mass properties base
    // on its shape.
    body->SetMassFromShapes();
    PhysicObject* p = new PhysicObject(img, body);

    ObjectList.push_back(p);

    return p;

}
void PhysicManager::RemoveObject(PhysicObject* object)
{
    std::list<PhysicObject*>::iterator it =  std::find(ObjectList.begin(),ObjectList.end(),object);
    ObjectListIterator = ObjectList.erase(it);
    delete object;
}
PhysicManager& PhysicManager::GetInstance()
{
    return mInstance;
}
PhysicManager* PhysicManager::GetInstancePtr()
{
    return &mInstance;
}
PhysicManager::~PhysicManager()
{
    Core::GetInstance().RemoveFrameListener(this);
    //dtor
}
